﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace PlayDeezGames.Common
{
    public abstract class StateMachine<StateId> : MessageHandlerBase
    {
        private StateId currentStateId = default(StateId);
        private Dictionary<StateId, State<StateId>> states = new Dictionary<StateId, State<StateId>>();
        private Stack<StateId> stack = new Stack<StateId>();
        protected abstract int CompareStateId(StateId first, StateId second);
        protected State<StateId> this[StateId index]
        {
            get
            {
                if (states.ContainsKey(index))
                {
                    return states[index];
                }
                return null;
            }
            set
            {
                if (index == null)
                {
                    throw new NotImplementedException();
                }
                states[index] = value;
                if (CompareStateId(index,CurrentStateId)==0)
                {
                    CurrentStateId = index;
                }
            }
        }
        protected void Step()
        {
            if (CurrentState != null)
            {
                if (CurrentState.Finished)
                {
                    CurrentStateId = CurrentState.ExitState;
                    Step();
                    return;
                }
                else
                {
                    CurrentState.OnMessage(new MessageBase(State<StateId>.MSGID_IdleState));
                    return;
                }
            }
            else
            {
                if (stack.Count == 0)
                {
                    HandleMessage(new MessageBase(MSGID_Done));
                }
                else
                {
                    CurrentStateId = stack.Pop();
                    Step();
                }
            }
        }
        protected StateId CurrentStateId
        {
            get
            {
                return currentStateId;
            }
            set
            {
                if (CurrentState != null)
                {
                    CurrentState.OnMessage(new MessageBase(State<StateId>.MSGID_FinishState));
                    CurrentState.Parent = null;
                }
                currentStateId = value;
                if (CurrentState != null)
                {
                    CurrentState.Parent = this;
                    CurrentState.OnMessage(new MessageBase(State<StateId>.MSGID_StartState));
                }
            }
        }
        public StateMachine(MessageHandlerBase theParent, StateId theStateId):base(theParent)
        {
            stack.Push(theStateId);
        }
        public State<StateId> CurrentState
        {
            get
            {
                return this[CurrentStateId];
            }
        }
        public override bool OnMessage(MessageBase theMessage)
        {
            if (theMessage.MessageId == MSGID_PushState)
            {
                stack.Push(CurrentStateId);
                return true;
            }
            else if (theMessage.MessageId == MSGID_Step)
            {
                Step();
                return true;
            }
            else
            {
                return base.OnMessage(theMessage);
            }
        }

        public static void MSGID_Step() { }
        public static void MSGID_Done() { }
        public static void MSGID_PushState() { }
    }
}
